/**
 * @file   Module.java
 * @author Enrique Madrid <e.madrid@lpcsite.com>
 * @date   Mon Jul 16 23:47:28 2007
 * 
 * @brief  Módulo ejecutable.
 * 
 */

package sim.framework;

import javax.microedition.lcdui.*;
import sim.framework.gui.*;

/**
 * @brief Módulo ejecutable.
 *
 * Las clases cuyas intancias quieren ser ejecutadas en el framework SIMP debe extender
 * la clase abstracta Module.
 *
 * @author Enrique J. Madrid M.
 * @version %I%, %I%
 * @since 1.0
 * @see Executable
 * @see Actions
 * @see Worker
 * @see Simlet
 */
public abstract class Module implements Executable, EventListener {

    protected   Simlet  m_Simlet;
    protected   int     m_modID;

    /** 
     * @brief Constructor.
     * 
     * @param id Identificador del módulo.
     * @param s Referencia al Simlet.
     * 
     * @return Devuelve una referencia a un objeto del tipo Module.
     */    
    public Module(int id, Simlet s) {
	m_modID = id;
	m_Simlet = s;
    }

    /** 
     * @brief Método ejecutado por el framework en segundo plano.
     *
     * @param msg Parametros pasados por el ejecutor de módulos del framework (Worker). 
     *            la función msg.getWParam() devuelve el estado pasado por el método
     *            todo() o uno de los especificados en Executable.work().
     *
     * @see Executable.work().
     * @see todo().
     */
    public abstract void work(final Msg msg);


    /** 
     * @brief Notificación de eventos del framework.
     *
     * Un modulo debe redefinir este método para recibir notificación de los eventos
     * del framework. Estos puede darse por acciones del usuario, o alarmas programadas.
     * 
     * @param msg Parametros pasados por el framework.
     * 
     * @return Devuelve true si el módulo despachó el evento, en caso
     *         contrario devuelve false.
     */
    public boolean event(final Msg msg) {
	return false;
    }

    protected final synchronized void setGui(Gui gui) {
	m_Simlet.setGui(gui);
    }

    protected final Gui getGui() {
	return m_Simlet.getGui();
    }

    /**
     * Ejecucion de módulos (Controlers)
     * 
     */

    /** 
     * @brief Crea un módulo para su ejecución o encolamiento.
     * 
     * @param id Indentificador del módulo
     * 
     * @return Devuelve una referencia al módulo creado.
     *
     * @see Module.exec();
     * @see Module.execQueue();
     */
    protected Module createModule(int id) {
	return m_Simlet.createModule(id);
    }

    /** 
     * @brief Solita al framework la ejecución de un módulo por demanda.
     * 
     * @param m Referencia a un objeto devuelto por Module.createModule().
     *
     * @see Module.createModule().
     * @see Module.execQueue()
     */
    protected final void exec(Module m) {
	m_Simlet.exec(m);
    }

    /** 
     * @brief Registra los módulos a ejecutar en caso de éxito o fracaso.
     *
     * Este método registra los módulos que serán ejecutados si un módulo 
     * notifica al framework que su ejecución ha tenido éxito o que ha
     * fracasado.
     * 
     * @param back Módulo a ejecutar en caso de fracaso.
     * @param next Módulo a ejecutar en caso de éxito.
     * @see Module.createModule()
     * @see Module.exec()
     */
    protected final void execQueue(Module back, Module next) {
	m_Simlet.execQueue(back, next);
    }

    /** 
     * @brief Notifica al framework que la ejecución del módulo a fracasado.
     *
     * @see Module.execQueue()
     */
    protected void execBack() {
	m_Simlet.execBack();
    }

    /** 
     * @brief Notifica al framework que la ejecución del módulo a tenido éxito.
     * 
     * @see Module.execQueue()
     */
    protected void execNext() {
	m_Simlet.execNext();
    }

    /** 
     * @brief Pone al modulo a ejecutar trabajo en segundo plano.
     * 
     * @param state Estado que se desea enviar en el mensaje a la función Module.work(),
     *              este valor debe ser mayor a Executable.STATE_USER.
     *
     * @see Module.work()
     */
    protected final void todo(int state) {
	m_Simlet.work(this, state);
    }

    /** 
     * @brief Determina si el módulo está ejecutando trabajo en segundo plano.
     * 
     * 
     * @return Devuelve true si el módulo esta ejecutando trabajo en segundo plano,
     *         en caso contrario devuelve false.
     */
    public final boolean isWorking() {
	return true;
    }
    
    /**
     * Administracion de documentos (Models)
     * 
     */

    /** 
     * @brief Guarda una referencia a un documento en el administrador de documentos.
     * 
     * @param id Indentificador del documento.
     * @param doc Documento. Puede ser null si queremos que el administrador
     *            deje de mantener una referencia del documento.
     */
    protected final void setDocument(int id, Document doc) {
        m_Simlet.m_Documents.change(id, doc);
    }

    /** 
     * Guarda un documento asociado al ID del módulo en el administrador de documentos.
     * 
     * @param doc Documento que se desea guardar.
     */
    protected final void setDocument(Document doc) {
        m_Simlet.m_Documents.change(m_modID, doc);
    }
    
    /** 
     * @brief Recupera un documento del administrador de documentos.
     * 
     * @param id Identificador del documento.
     * 
     * @return Devuelve una referencia del documento que se encuentra en el administrador
     *         en caso contrario devuelve NULL.
     */
    protected final Document getDocument(int id) {
        return m_Simlet.m_Documents.search(id);
    }

    /** 
     * Recupera el documento asociado al ID del paquete en el administrador de documentos
     * 
     * @return Devuelve una referencia del documento que se encuentra en el administrador
     *         en caso contrario devuelve NULL.
     */
    protected final Document getDocument() {
        return m_Simlet.m_Documents.search(m_modID);
    }

    /*
     *  Returns an Image from the Resource.
     *  @param  id  ID of the resource to load
     *  @return The requested Image, or NULL if fails.
     */
    protected final Image getImage( int id ) {
        return m_Simlet.getImage(id);
    }
    
    /**
     *  Devuelve la etiqueta asociada al ID.
     *
     *  @param  id  Identificador de la etiqueta.
     *  @return Si tiene éxito debuelve una referencia a la cadena. En caso contrario
     *          devuelve null.
     */
    protected final String getLabel( int id ) {
        return m_Simlet.getLabel(id);
    }        

    /**
     * Funciones para acceso a valores de configuración de la aplicación
     * 
     */

    protected final boolean getAppCfgCommit() {
	return m_Simlet.m_AppCfg.m_Commit;
    }

    protected final int getAppCfgSyncPer() {
	return m_Simlet.m_AppCfg.m_SyncPer;
    }

    protected final int getAppCfgTimeOut() {
	return m_Simlet.m_AppCfg.m_TimeOut;
    }

    protected final boolean getAppCfgBatch() {
	return m_Simlet.m_AppCfg.m_Batch;
    }

    protected final String getAppEncoding() {
	return m_Simlet.getAppEncoding();
    }

    public final String decoding(byte[] bytes, int start, int length) {
	return m_Simlet.decoding(bytes, start, length);
    }

    public final byte[] encoding(final String string) {
	return m_Simlet.encoding(string);
    }
}
